Part 12: 暗号化されたデータを使ってのディープラーニング

このnotebookでは、これまでに学んだテクニックの全てを駆使して、暗号化されたモデルと暗号化されたデータを使ってニューラルネットワークのトレーニング、そして推論をを行います。

特に、暗号化されたデータを使って微分を計算できる、"Autograd Engine"について紹介します。

Authors:

Step 1: ワーカーの作成とトイデータの準備

トイデータはトイモデル(初歩的なモデル)で使用するデータセットの事です


In [ ]:
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import syft as sy

In [ ]:
# Set everything up
hook = sy.TorchHook(torch) 

alice = sy.VirtualWorker(id="alice", hook=hook)
bob = sy.VirtualWorker(id="bob", hook=hook)
james = sy.VirtualWorker(id="james", hook=hook)

In [ ]:
# A Toy Dataset
data = torch.tensor([[0,0],[0,1],[1,0],[1,1.]])
target = torch.tensor([[0],[0],[1],[1.]])

# A Toy Model
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.fc1 = nn.Linear(2, 2)
        self.fc2 = nn.Linear(2, 1)

    def forward(self, x):
        x = self.fc1(x)
        x = F.relu(x)
        x = self.fc2(x)
        return x
model = Net()

Step 2: モデルとデータの暗号化

暗号化は2つのステップで実行されます。ステップ1では、"Secure Multi-Party Computation"が整数でしか動作しないため、"Fixed Precision"を使って不動小数点型のオブジェクトを整数型にエンコードしますy。これは.fix_precision()で実現できます。

ステップ2では、.share()を使ってデータを実際に暗号化します。この例ではsharesをAliceとBobに分割して送信してします。

こので注意すべき点はrequires_gradプロパティをTrueにセットしておくことです。こうしておくことで暗号化されたデータに対してもautogradが適用できるようになります。実をいうと、"Secure Multi-Party Computation"は整数でしか動きませんが、PyTorchデフォルトのautogradは不動少数でしか動きません。そのため、私たちは特別なAutogradTensorを自作する必要がありました。print関数を使えば各エレメントにAutogradTensorが含まれているかどうか確認できますよ。


In [ ]:
# 全て暗号化しておきます
data = data.fix_precision().share(bob, alice, crypto_provider=james, requires_grad=True)
target = target.fix_precision().share(bob, alice, crypto_provider=james, requires_grad=True)
model = model.fix_precision().share(bob, alice, crypto_provider=james, requires_grad=True)

In [ ]:
print(data)

Step 3: トレーニング

簡単なトレーニングロジックでモデルのトレーニングができます。


In [ ]:
opt = optim.SGD(params=model.parameters(),lr=0.1).fix_precision()

for iter in range(20):
    # 1) 前回の微分の計算結果をクリアしておきます。(もしあれば)
    opt.zero_grad()

    # 2) 予測を行います
    pred = model(data)

    # 3) ロスを計算します
    loss = ((pred - target)**2).sum()

    # 4) 勾配ベクトルを計算します
    loss.backward()

    # 5) モデルのウェイトを更新します
    opt.step()

    # 6) 確認のため、状況を出力します
    print(loss.get().float_precision())

ロスはちゃんと下がっていますね。

Fixed Precisionの影響

モデルからデータまで、全てを暗号化してしまって、トレーニングに影響は無いのか、期待通りロスが下がるのか、気になりますよね。でも、暗号化はされていても、行われているコンピューテーションは、理論上は、同じです。実際、暗号化環境下でのトレーニングも通常のトレーニングも結果はほぼ同じです。同じモデルを同じデータで暗号化せずにトレーニングしてみてください。その際には初期値にを固定して、同じものを使う必要があります。

モデルを初期化したい場合は、例えば、__init__の中で:

with torch.no_grad():
    self.fc1.weight.set_(torch.tensor([[ 0.0738, -0.2109],[-0.1579,  0.3174]], requires_grad=True))
    self.fc1.bias.set_(torch.tensor([0.,0.1], requires_grad=True))
    self.fc2.weight.set_(torch.tensor([[-0.5368,  0.7050]], requires_grad=True))
    self.fc2.bias.set_(torch.tensor([-0.0343], requires_grad=True))

を実行してみてください。

気がついたかもしれませんが、唯一の違いは"fixed precision"を使って少数を整数に変更したり、整数を少数に戻したりする時に誤差が生じるということです。デフォルトのprecision_fractionalの値は3です。この値を2にすると誤差は大きくなります。もし、誤差をさらに小さくしたい場合はprecision_fractional = 4を試してみても良いかもしれません。

おめでとうございます!コミュニティに入ろう!

本チュートリアルを完了しました。おめでとうございます!もし、このチュートリアルを気に入って、プライバシーに配慮した非中央集権的なAI技術や付随する(データやモデルの)サプライチェーンにご興味があって、プロジェクトに参加したいと思われるなら、以下の方法で可能です。

PySyftのGitHubレポジトリにスターをつける

一番簡単に貢献できる方法はこのGitHubのレポジトリにスターを付けていただくことです。スターが増えると露出が増え、より多くのデベロッパーにこのクールな技術の事を知って貰えます。

Slackに入る

最新の開発状況のトラッキングする一番良い方法はSlackに入ることです。 下記フォームから入る事ができます。 http://slack.openmined.org

コードプロジェクトに参加する

コミュニティに貢献する一番良い方法はソースコードのコントリビューターになることです。PySyftのGitHubへアクセスしてIssueのページを開き、"Projects"で検索してみてください。参加し得るプロジェクトの状況を把握することができます。また、"good first issue"とマークされているIssueを探す事でミニプロジェクトを探すこともできます。

寄付

もし、ソースコードで貢献できるほどの時間は取れないけど、是非何かサポートしたいという場合は、寄付をしていただくことも可能です。寄附金の全ては、ハッカソンやミートアップの開催といった、コミュニティ運営経費として利用されます。

OpenMined's Open Collective Page


In [ ]: